﻿using NationalInstruments.DAQmx;
using System;
using System.Collections.Generic;
using System.Threading;

public class ContinuousPressureReader : IDisposable
{
    // 传感器参数
    private readonly double _excitationVoltage;

    private readonly double _sensitivity;        // mV/V
    private readonly double _fullScaleLoad;      // N
    private double _zeroOffsetMilliVPerV;        // 零点偏移 (mV/V)

    // 采集参数
    private readonly string _deviceName;

    private readonly int _index;
    private readonly double _samplingRate;
    private readonly int _bufferSize;

    // DAQmx组件
    private Task _analogTask;

    private AnalogSingleChannelReader _reader;
    private AsyncCallback _asyncCallback;
    private volatile bool _isRunning;

    // 数据存储
    private readonly List<double> _rawMilliVPerVData; // 存储原始mV/V数据

    private readonly object _dataLock = new object();

    public event Action<double[]> OnDataProcessingComplete;

    public event Action<string> OnLogMessage; // 新增日志事件

    public ContinuousPressureReader(string deviceName, int index, double excitationVoltage,
                                  double sensitivity, double fullScaleLoad,
                                  double samplingRate = 10240, int bufferSize = 1000)
    {
        _deviceName = deviceName;
        _index = index;
        _excitationVoltage = excitationVoltage;
        _sensitivity = sensitivity; // 单位: mV/V
        _fullScaleLoad = fullScaleLoad;
        _samplingRate = samplingRate;
        _bufferSize = bufferSize;

        _rawMilliVPerVData = new List<double>(100000);
        _asyncCallback = new AsyncCallback(ReadCallback);
    }

    /// <summary>
    /// 执行零点校准（必须在开始采集前调用）
    /// </summary>
    public void PerformZeroCalibration(int calibrationSamples = 100)
    {
        LogMessage("开始零点校准...");

        using (var calibrationTask = new Task())
        {
            calibrationTask.AIChannels.CreateBridgeChannel(
    GetChannelName(),          // 物理通道（如 "cDAQ1Mod1/ai0"）
    "",                        // 自定义通道名（可空）
    0.0,                       // 最小量程 (mV/V)
    25.0,                      // 最大量程 (mV/V)
    AIBridgeUnits.MillivoltsPerVolt,
    AIBridgeConfiguration.FullBridge, // 全桥（确认传感器接线）
    AIExcitationSource.Internal,
    5.0,                       // 激励电压 (5.0V)
    350.0                     // 桥路标称电阻 ★ 修正为 350 Ω ★
);

            calibrationTask.Timing.ConfigureSampleClock(
                "",
                _samplingRate,
                SampleClockActiveEdge.Rising,
                SampleQuantityMode.FiniteSamples,
                calibrationSamples
            );

            var reader = new AnalogSingleChannelReader(calibrationTask.Stream);
            calibrationTask.Start();

            double[] samples = reader.ReadMultiSample(calibrationSamples);
            calibrationTask.Stop();

            double sum = 0;
            foreach (double sample in samples) sum += sample;
            double avgMilliVPerV = sum / calibrationSamples;
            _zeroOffsetMilliVPerV = avgMilliVPerV;
            //_zeroOffsetMilliVPerV = -0.01;

            LogMessage($"零点校准完成: {avgMilliVPerV:F2} mV/V");

            // 检查异常值
            if (Math.Abs(avgMilliVPerV) > 50)
            {
                LogMessage("警告: 零点偏移过大! 检查传感器接线或安装");
            }
        }
    }

    /// <summary>
    /// 开始连续采集
    /// </summary>
    public void Start()
    {
        if (_isRunning) return;

        lock (_dataLock)
        {
            _rawMilliVPerVData.Clear();
        }

        _analogTask = new Task();
        _analogTask.AIChannels.CreateBridgeChannel(
    GetChannelName(),          // 物理通道（如 "cDAQ1Mod1/ai0"）
    "",                        // 自定义通道名（可空）
    0.0,                       // 最小量程 (mV/V)
    25.0,                      // 最大量程 (mV/V)
    AIBridgeUnits.MillivoltsPerVolt,
    AIBridgeConfiguration.FullBridge, // 全桥（确认传感器接线）
    AIExcitationSource.Internal,
    5.0,                       // 激励电压 (5.0V)
    350.0                     // 桥路标称电阻 ★ 修正为 350 Ω ★
);

        // 配置连续采样
        _analogTask.Timing.ConfigureSampleClock(
            "",
            _samplingRate,
            SampleClockActiveEdge.Rising,
            SampleQuantityMode.ContinuousSamples,
            _bufferSize * 2
        );

        _reader = new AnalogSingleChannelReader(_analogTask.Stream);
        _analogTask.Control(TaskAction.Verify);
        _analogTask.Start();

        _isRunning = true;

        // 开始异步读取
        _reader.SynchronizeCallbacks = true;
        _reader.BeginReadMultiSample(_bufferSize, _asyncCallback, null);

        LogMessage("连续采集已启动");
    }

    /// <summary>
    /// 停止采集并处理所有数据点
    /// </summary>
    public void Stop()
    {
        if (!_isRunning) return;

        _isRunning = false;

        // 等待最后一次读取完成
        Thread.Sleep(200);

        if (_analogTask != null)
        {
            _analogTask.Stop();
            _analogTask.Dispose();
            _analogTask = null;
        }

        // 处理所有采集到的数据
        ProcessCollectedData();

        LogMessage("采集已停止");
    }

    private void ReadCallback(IAsyncResult ar)
    {
        try
        {
            if (!_isRunning) return;

            // 获取读取的数据 (单位: mV/V)
            double[] newData = _reader.EndReadMultiSample(ar);
            // 存储数据
            lock (_dataLock)
            {
                _rawMilliVPerVData.AddRange(newData);
            }

            // 继续下一次异步读取
            if (_isRunning)
            {
                _reader.BeginReadMultiSample(_bufferSize, _asyncCallback, null);
            }
        }
        catch (DaqException ex)
        {
            LogMessage($"读取错误: {ex.Message}");
            Stop();
        }
    }

    private void ProcessCollectedData()
    {
        double[] allMilliVPerVData;
        lock (_dataLock)
        {
            allMilliVPerVData = _rawMilliVPerVData.ToArray();
        }

        if (allMilliVPerVData.Length == 0)
        {
            LogMessage("无数据可处理");
            return;
        }

        // 记录原始数据统计信息
        double minRaw = allMilliVPerVData[0], maxRaw = allMilliVPerVData[0];
        double sumRaw = 0;
        foreach (double value in allMilliVPerVData)
        {
            if (value < minRaw) minRaw = value;
            if (value > maxRaw) maxRaw = value;
            sumRaw += value;
        }
        double avgRaw = sumRaw / allMilliVPerVData.Length;

        LogMessage($"原始数据统计: 点数={allMilliVPerVData.Length}, 平均={avgRaw:F1} mV/V, 范围={minRaw:F1}~{maxRaw:F1} mV/V");

        // 转换为牛顿
        double[] forceData = ConvertToNewton(allMilliVPerVData);

        // 记录转换后数据统计信息
        double minForce = forceData[0], maxForce = forceData[0];
        double sumForce = 0;
        foreach (double value in forceData)
        {
            if (value < minForce) minForce = value;
            if (value > maxForce) maxForce = value;
            sumForce += value;
        }
        double avgForce = sumForce / forceData.Length;

        LogMessage($"力数据统计: 平均={avgForce:F1} N, 范围={minForce:F1}~{maxForce:F1} N");

        // 触发事件
        OnDataProcessingComplete?.Invoke(forceData);
    }

    private double[] ConvertToNewton(double[] milliVPerVData)
    {
        // 计算转换因子 = 满量程力(N) / 灵敏度(mV/V)
        double conversionFactor = _fullScaleLoad / _sensitivity; // ≈6238.5 N/(mV/V)

        double[] result = new double[milliVPerVData.Length];
        for (int i = 0; i < milliVPerVData.Length; i++)
        {
            // 直接使用归一化值转换
            result[i] = (milliVPerVData[i]-_zeroOffsetMilliVPerV) * conversionFactor;
        }
        return result;
    }

    private string GetChannelName()
    {
        return $"{_deviceName}/ai{_index}";
    }

    private void LogMessage(string message)
    {
        OnLogMessage?.Invoke($"{DateTime.Now:HH:mm:ss.fff} - {message}");
        Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff} - {message}");
    }

    public void Dispose()
    {
        Stop();
    }
}